# gozerbot/fleet.py
#
#

""" fleet is a list of bots """

__copyright__ = 'this file is in the public domain'

from gozerbot.datadir import datadir
from gozerbot.generic import rlog, handle_exception, waitforqueue
from gozerbot.ircevent import Ircevent
from gozerbot.persist import Persist
from gozerbot.config import config
from gozerbot.bot import Bot
from gozerbot.plugins import plugins
import gozerbot.thr as thr
import Queue

class Fleet(object):

    """ contains multiple bots (list of bots) """

    def __init__(self, fname):
        self.botdata = Persist(fname)
        if not self.botdata.data:
            self.botdata.data = {}
        self.bots = []

    def size(self):
        """ return number of bots """
        return len(self.bots)

    def start(self, mainbot=None):
        """ startup the bots """
        if mainbot:
            self.bots.append(mainbot)
        for i, j in self.botdata.data.iteritems():
            self.add(i, *j)

    def save(self):
        """ save fleet data and call save on all the bots """
        try:
            self.botdata.save()
        except Exception, ex:
            handle_exception()

    def list(self):
        """ return list of bot names """
        result = []
        for i in self.bots:
            result.append(i.name)
        return result

    def stopall(self):
        """ return bot by name """
        for i in self.bots:
            try:
                i.stop()
            except:
                pass

    def byname(self, name):
        """ return bot by name """
        name = name.lower()
        for i in self.bots:
            if name == i.name:
                return i

    def add(self, name, nick, server, port, password=None, ipv6=None):
        """ call add thread for bot """
        if self.byname(name):
            rlog(10, 'fleet', 'we already have a bot named %s in fleet' % \
name)
            return
        thr.start_new_thread(self.addthread, (name, nick, server, port, \
password, ipv6))
        return 1

    def addthread(self, name, nick, server, port, password, ipv6):
        """ create bot and call connect """
        name = name.lower()
        try:
            rlog(10, 'fleet', 'creating %s bot for server %s' % (name, server))
            self.botdata.data[name] = (nick, server, port, password, ipv6)
            bot = Bot(config['owneruserhost'], name)
            self.bots.append(bot)
            self.botdata.save()
            bot.connect(nick, server, port, password, ipv6)
            rlog(10, 'fleet', 'added %s' % server)
        except Exception, ex:
            handle_exception()

    def connect(self, name):
        """ connect bot to irc server"""
        name = name.lower()
        for i in self.bots:
            if i.name == name:
                try:
                    data = self.botdata.data[name]
                except:
                    return
                thr.start_new_thread(i.connect, data)
                return 1

    def delete(self, name):
        """ delete bot with name from fleet """
        name = name.lower()
        for i in self.bots:
            if i.name == name:
                i.exit()
                try:
                    del self.botdata.data[name]
                    self.botdata.save()
                except:
                    pass
                self.remove(i)
                rlog(10, 'fleet', '%s deleted' % i.name)
                return 1

    def remove(self, bot):
        """ delete bot by object """
        self.bots.remove(bot)

    def exit(self, name):
        """ call exit on all bots """
        name = name.lower()
        for i in self.bots:
            if i.name == name:
                try:
                    i.exit()
                except:
                    pass
                return 1

    def exitall(self):
        """ call exit on all bots """
        for i in self.bots:
            try:
                i.exit()
            except Exception, ex:
                handle_exception()

    def cmnd(self, ievent, name, cmnd):
        """ do command on a bot by name """
        name = name.lower()
        bot = self.byname(name)
        if not bot:
            return 0
        j = Ircevent()
        j.copyin(ievent)
        j.txt = cmnd
        q = Queue.Queue()
        j.queues = [q]
        j.speed = 3
        plugins.trydispatch(bot, j)
        result = waitforqueue(q)
        for res in result:
            ievent.reply("[%s] %s" % (bot.name, res))

    def cmndall(self, ievent, cmnd):
        """ do a command on all bots """
        threads = []
        for i in self.bots:
            thread = thr.start_new_thread(self.cmnd, (ievent, i.name, cmnd))
            threads.append(thread)
        for i in threads:
            i.join(10)

fleet = Fleet(datadir + '/fleet')
